package com.frame.filter

import com.frame.verify.IParamVerify
import com.frame.verify.ParameterVerifyFactory
import com.frame.verify.annotation.Chain
import com.frame.verify.annotation.Param
import com.frame.verify.annotation.ParamVerify
import org.glassfish.jersey.message.internal.MediaTypes
import org.glassfish.jersey.message.internal.ReaderWriter
import org.glassfish.jersey.server.ContainerRequest
import org.slf4j.Logger
import org.slf4j.LoggerFactory

import javax.servlet.http.HttpServletRequest
import javax.ws.rs.container.ContainerRequestContext
import javax.ws.rs.container.ContainerRequestFilter
import javax.ws.rs.container.ResourceInfo
import javax.ws.rs.core.Context
import javax.ws.rs.core.Form
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.MultivaluedMap

/**
 * 请求权限过滤器
 *
 * Created by three on 14-7-30.
 * User: 王利平
 */
class ParameterVerifyFilter implements ContainerRequestFilter {

    private Logger log = LoggerFactory.getLogger(ParameterVerifyFilter.class);

    @Context
    private ResourceInfo resourceInfo;
    @Context
    private HttpServletRequest httpServletRequest;

    @Override
    void filter(ContainerRequestContext requestContext) throws IOException {
        log.info("用户请求"+resourceInfo.getResourceClass().name+'.'+resourceInfo.getResourceMethod().name+"参数验证")

        ParamVerify pVerify = resourceInfo.getResourceMethod().getAnnotation(ParamVerify.class);
        if (null == pVerify) {
            return;
        }
        Param[] params = pVerify.params();

        List<Map<String, Object>> errorParamsDesc = new ArrayList<Map<String,Object>>();

        ContainerRequest request = requestContext.getRequest()
//        (request.getUriInfo() as ExtendedUriInfo).
        MultivaluedMap<String, String> queryParams = requestContext.getUriInfo().getQueryParameters();
        MultivaluedMap<String, String> pathParams = requestContext.getUriInfo().getQueryParameters();
//        MultivaluedMap<String, String> formParams = getFormParameters(requestContext).asMap();
        // 解析用户参数
        for(Param param : params) {
            Object pValue = queryParams.getFirst(param.name());
//            pValue = pValue==null? formParams.getFirst(param.name()): pValue;
            pValue = pValue==null? pathParams.getFirst(param.name()): pValue;
            System.out.println(param.name()+"=>"+pValue);

            for(Chain chain:param.chain()) {
                try {
                    IParamVerify pv = ParameterVerifyFactory.chainNode(chain.cls());
                    IParamVerify.VerifyResult vr = pv.verify(pValue, chain.p(), chain.msg());
                    if(!vr.flag()) { // 一个chain节点失败，停止后面所有节点验证
                        Map<String, Object> ep = new HashMap<String, Object>();
                        ep.put("name", param.name());
                        ep.put("flag", vr.flag());
                        ep.put("msg", vr.message());
                        errorParamsDesc.add(ep);
                        break;
                    }
                } catch (InstantiationException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }

        // 判断是否有参数失败
        if(errorParamsDesc.size()>=1) {
//            requestContext.abortWith(Response
//                                    .status(Response.Status.BAD_REQUEST)
//                                    .type(MediaType.APPLICATION_JSON)
//                                    .entity(errorParamsDesc)
//                                    .build());
        }

    }

    /**
     * 得到form参数
     * @param requestContext
     * @return
     */
    private Form getFormParameters(ContainerRequestContext requestContext) {
        if (MediaTypes.typeEqual(MediaType.APPLICATION_FORM_URLENCODED_TYPE, requestContext.getMediaType())) {
//            httpServletRequest.getInputStream();
            InputStream inputStream = requestContext.getEntityStream();
            byte[] tempStream = null;
            if (inputStream.getClass() != ByteArrayInputStream.class) {
                // Buffer input
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                try {
                    ReaderWriter.writeTo(inputStream, byteArrayOutputStream);
                } catch (IOException e) {
                    throw new IllegalArgumentException(e);
                }
                tempStream = byteArrayOutputStream.toByteArray();
                inputStream = new ByteArrayInputStream(tempStream);
                requestContext.setEntityStream(inputStream);
            }

            ContainerRequest request = (ContainerRequest)requestContext.getRequest();
            Form f = request.readEntity(Form.class);

            requestContext.setEntityStream(new ByteArrayInputStream(tempStream));

            return f;
        } else {
            return new Form();
        }
    }
}
